#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <regex.h>
#include <cjson/cJSON.h>
#include <iperf_api.h>
#include <stdint.h>
#include <sys/select.h>
#include <netdb.h>
#include <ifaddrs.h>
#include "net_utils.h"
#define MAX_BUFFER_SIZE 1024

// 包头大小
#define HEADER_SIZE 4

typedef struct icmp_hdr
{
    unsigned char icmp_type;      // 消息类型
    unsigned char icmp_code;      // 代码
    unsigned short icmp_checksum; // 校验和
    // 下面是回显头
    unsigned short icmp_id;       // 用来惟一标识此请求的ID号，通常设置为进程ID
    unsigned short icmp_sequence; // 序列号
    unsigned long icmp_timestamp; // 时间戳
} ICMP_HDR;

// 包头结构体，定义为4字节表示ips个数
typedef struct
{
    int count; // ips数组的个数
} PacketHeader;

static int sockfd;
int *ret = NULL;

int is_valid_ip(const char *ip)
{
    // 定义匹配IP地址的正则表达式
    const char *pattern = "^([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})$";

    regex_t regex;
    regcomp(&regex, pattern, REG_EXTENDED);

    // 匹配输入的IP地址
    if (regexec(&regex, ip, 0, NULL, 0) == 0)
    {
        // 如果匹配成功，进一步检查每一部分是否在0-255之间
        int octets[4];
        if (sscanf(ip, "%d.%d.%d.%d", &octets[0], &octets[1], &octets[2], &octets[3]) == 4)
        {
            for (int i = 0; i < 4; i++)
            {
                if (octets[i] < 0 || octets[i] > 255)
                {
                    regfree(&regex);
                    return 0; // IP地址不合法
                }
            }
            regfree(&regex);
            return 1; // IP地址合法
        }
    }

    regfree(&regex);
    return 0; // IP地址不合法
}

// 计算校验和
static unsigned short
checksum(void *b, int len)
{
    unsigned short *buf = (unsigned short *)(b);
    unsigned int sum = 0;
    unsigned short result;

    for (sum = 0; len > 1; len -= 2)
    {
        sum += *buf++;
    }

    if (len == 1)
    {
        sum += *(unsigned char *)buf;
    }

    sum = (sum >> 16) + (sum & 0xFFFF);
    sum += (sum >> 16);
    result = ~sum;
    return result;
}

// 创建 ICMP 请求报文
static void create_icmp_packet(char *packet, int seq_num)
{
    ICMP_HDR *icmp_hdr = (ICMP_HDR *)packet;

    // 设置 ICMP 类型 (Echo请求 type = 8)
    icmp_hdr->icmp_type = 8;
    icmp_hdr->icmp_code = 0;
    icmp_hdr->icmp_checksum = 0;
    icmp_hdr->icmp_id = htons(getpid());
    icmp_hdr->icmp_sequence = htons(seq_num);

    // 填充数据部分，可以为任意
    memset(&packet[sizeof(ICMP_HDR)], 'E', 32);
    struct timeval time_sent;
    gettimeofday(&time_sent, NULL);
    icmp_hdr->icmp_timestamp = time_sent.tv_sec * 1000 + time_sent.tv_usec / 1000;

    // 计算校验和
    icmp_hdr->icmp_checksum = checksum(icmp_hdr, sizeof(ICMP_HDR) + 32);
}
void net_deley_init()
{
    if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
    {
        perror("Socket creation failed, please call net_deley_init() once\n");
        return;
    }
    int ttl = 64;
    // 设置套接字选项
    setsockopt(sockfd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
}
static char *get_local_ip()
{
    struct ifaddrs *ifaddr, *ifa;
    char *local_ip = (char *)malloc(INET_ADDRSTRLEN); // IPv4 max length

    if (getifaddrs(&ifaddr) == -1)
    {
        perror("getifaddrs failed");
        return NULL;
    }

    // Iterate through the list of interfaces
    for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
    {
        // Look specifically for eth0 interface
        if (ifa->ifa_addr && strcmp(ifa->ifa_name, "eth0") == 0)
        {
            // Check if it is an IPv4 address (AF_INET)
            if (ifa->ifa_addr->sa_family == AF_INET)
            {
                struct sockaddr_in *sa = (struct sockaddr_in *)ifa->ifa_addr;
                // Convert the IP address to a string
                inet_ntop(AF_INET, &sa->sin_addr, local_ip, INET_ADDRSTRLEN);
                freeifaddrs(ifaddr);
                return local_ip;
            }
        }
    }

    freeifaddrs(ifaddr);
    printf("Unable to find IP address for interface eth0\n");
    return NULL;
}
int *get_net_delay(int size, char **ips)
{
    if (sockfd <= 0)
    {
        printf("call net_delay_init() first\n");
        return NULL;
    }

    if (ret != NULL)
    {
        free(ret);
    }

    ret = (int *)malloc(size * sizeof(int));
    if (ret == NULL)
    {
        perror("Memory allocation failed");
        return NULL;
    }

    struct sockaddr_in target_addr;
    char packet[sizeof(ICMP_HDR) + 32] = {'0'};
    struct timeval start_time, end_time;
    int seq_num = 0;
    char *local_ip = get_local_ip();
    // printf("local_ip: %s\n", local_ip);
    for (int i = 0; i < size; i++)
    {
        ret[i] = 1e9; // Set to a very large value initially

        if (!is_valid_ip(ips[i]))
        {
            printf("ip is not valid\n");
            continue;
        }

        // If the IP is the local machine's IP, set RTT to 0
        if (strcmp(ips[i], local_ip) == 0)
        {
            ret[i] = 0;
            continue;
        }

        memset(&target_addr, 0, sizeof(target_addr));
        target_addr.sin_family = AF_INET;
        target_addr.sin_port = htons(0);
        target_addr.sin_addr.s_addr = inet_addr(ips[i]);

        // Send and receive Ping request
        for (seq_num = 1; seq_num <= 4; seq_num++)
        {
            // Create ICMP request packet
            create_icmp_packet(packet, seq_num);
            gettimeofday(&start_time, NULL);

            if (sendto(sockfd, packet, sizeof(ICMP_HDR) + 32, 0, (struct sockaddr *)&target_addr, sizeof(target_addr)) < 0)
            {
                perror("Send failed");
                continue;
            }

            char recv_buf[1024];
            struct sockaddr_in recv_addr;
            socklen_t addr_len = sizeof(recv_addr);

            // Set a timeout for receiving data (1 second or 0.5 seconds)
            struct timeval timeout;
            timeout.tv_sec = 1; // Timeout 1 second
            timeout.tv_usec = 0;

            fd_set read_fds;
            FD_ZERO(&read_fds);
            FD_SET(sockfd, &read_fds);

            int select_result = select(sockfd + 1, &read_fds, NULL, NULL, &timeout);
            if (select_result <= 0) // No data received or timeout
            {
                printf("Timeout or error while receiving\n");
                continue;
            }

            int bytes_received = recvfrom(sockfd, recv_buf, sizeof(recv_buf), 0, (struct sockaddr *)&recv_addr, &addr_len);
            gettimeofday(&end_time, NULL);

            if (bytes_received < 20 + sizeof(ICMP_HDR)) // Ensure we received enough data
            {
                perror("Receive failed");
            }
            else
            {
                // Parse received ICMP packet
                int ip_header_len = (recv_buf[0] & 0x0F) * 4; // Calculate IP header length
                ICMP_HDR *pRecvIcmp = (ICMP_HDR *)(recv_buf + ip_header_len);

                if (pRecvIcmp->icmp_type == 0 && pRecvIcmp->icmp_id == htons(getpid()))
                {
                    // Valid echo reply received
                    int rtt = (end_time.tv_sec - start_time.tv_sec) * 1000000 +
                              (end_time.tv_usec - start_time.tv_usec); // Calculate RTT in microseconds

                    ret[i] = rtt; // Store the RTT in microseconds
                    break;        // Stop further sending once we get a response
                }
            }
            usleep(500000); // Sleep for 0.5 seconds between attempts
        }
    }
    return ret;
}
double get_average_delay(int size, char **ips)
{
    int *delays = get_net_delay(size, ips);
    if (delays == NULL)
    {
        return -1.0;
    }

    double sum = 0.0;
    int valid_count = 0;

    for (int i = 0; i < size; i++)
    {

        if (delays[i] < 1e9)
        {
            sum += delays[i];
            valid_count++;
        }
    }

    free(delays);

    if (valid_count == 0)
    {
        return -1.0;
    }

    return sum / valid_count;
}

// 发送ping结果函数给master
int send_ping_results(char *dest_ip, int dest_port, char **ips, int *ret, int ips_count)
{
    // 使用UDP
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        perror("Socket creation failed");
        return -1;
    }

    struct sockaddr_in target_addr;
    memset(&target_addr, 0, sizeof(target_addr));
    target_addr.sin_family = AF_INET;
    target_addr.sin_port = htons(dest_port);
    if (inet_pton(AF_INET, dest_ip, &target_addr.sin_addr) <= 0)
    {
        perror("Invalid destination IP address");
        close(sockfd);
        return -1;
    }

    char send_buf[MAX_BUFFER_SIZE];
    memset(send_buf, 0, MAX_BUFFER_SIZE);

    // 包头：保存ips_count
    PacketHeader header;
    header.count = ips_count;

    // 复制包头到缓冲区
    memcpy(send_buf, &header, HEADER_SIZE);

    // 填充数据部分：ip:延迟
    int offset = HEADER_SIZE;
    for (int i = 0; i < ips_count; i++)
    {
        // 格式为 "ip:延迟"
        int len = snprintf(send_buf + offset, MAX_BUFFER_SIZE - offset, "%s:%d ", ips[i], ret[i]);
        if (len < 0 || offset + len >= MAX_BUFFER_SIZE)
        {
            fprintf(stderr, "Buffer overflow while preparing message\n");
            close(sockfd);
            return -1;
        }
        offset += len;
    }

    if (sendto(sockfd, send_buf, offset, 0, (struct sockaddr *)&target_addr, sizeof(target_addr)) < 0)
    {
        perror("Send failed");
        close(sockfd);
        return -1;
    }

    printf("Ping results sent to %s:%d\n", dest_ip, dest_port);

    close(sockfd);
    return 0;
}

void net_deley_destroy()
{
    if (sockfd > 0)
    {
        close(sockfd);
    }
}

typedef void (*json_callback)(char *json_string);

// 用于存储累计结果
static double total_sent_bytes = 0.0;
static double total_received_bytes = 0.0;
static double total_time = 0.0;
static int interval_count = 0;

void process_json(char *json_str)
{
    // 解析 JSON 数据
    cJSON *root = cJSON_Parse(json_str);
    if (root == NULL)
    {
        // printf("Error parsing JSON\n");
        return;
    }

    // 获取 event 字段
    cJSON *event = cJSON_GetObjectItem(root, "event");
    if (!event || !cJSON_IsString(event) || strcmp(event->valuestring, "interval") != 0)
    {
        // printf("Invalid event or missing event field\n");
        cJSON_Delete(root);
        return;
    }

    // 获取 data 字段
    cJSON *data = cJSON_GetObjectItem(root, "data");
    if (!data)
    {
        // printf("Missing data field in JSON\n");
        cJSON_Delete(root);
        return;
    }

    // 获取 sum 字段
    cJSON *sum = cJSON_GetObjectItem(data, "sum");
    if (!sum)
    {
        // printf("Missing sum field in data\n");
        cJSON_Delete(root);
        return;
    }

    // 获取发送和接收的字节数
    cJSON *bytes_sent = cJSON_GetObjectItem(sum, "bytes");
    if (!bytes_sent)
    {
        // printf("Missing bytes field in sum\n");
        cJSON_Delete(root);
        return;
    }

    // 获取间隔时间
    cJSON *seconds = cJSON_GetObjectItem(sum, "seconds");
    if (!seconds)
    {
        /// printf("Missing seconds field in sum\n");
        cJSON_Delete(root);
        return;
    }

    // 累加字节数和时间
    total_sent_bytes += bytes_sent->valuedouble;
    total_received_bytes += bytes_sent->valuedouble; // 你可以根据实际需要来获取接收字节
    total_time += seconds->valuedouble;
    interval_count++;

    // // 输出当前的统计数据
    // printf("Interval %d: Sent bytes = %.2f, Time = %.2f seconds\n",
    //        interval_count, bytes_sent->valuedouble, seconds->valuedouble);

    // // 计算平均带宽
    // double avg_sent_bandwidth = total_sent_bytes / total_time;         // 平均上传带宽 (字节/秒)
    // double avg_received_bandwidth = total_received_bytes / total_time; // 平均下载带宽 (字节/秒)

    // printf("Average Sent Bandwidth: %.2f bytes/sec\n", avg_sent_bandwidth);
    // printf("Average Received Bandwidth: %.2f bytes/sec\n", avg_received_bandwidth);

    cJSON_Delete(root);
}

iperf_result_t iperf_measure_bandwidth(const char *host, int port, int duration)
{
    iperf_result_t result = {0.0, 0.0};
    struct iperf_test *test = NULL;

    total_sent_bytes = 0.0;
    total_received_bytes = 0.0;
    total_time = 0.0;
    interval_count = 0;

    // 参数检查
    if (!host || port <= 0 || port > 65535 || duration <= 0)
    {
        return result;
    }

    // 创建测试实例
    test = iperf_new_test();
    if (test == NULL)
    {
        return result;
    }

    // 配置测试参数
    iperf_defaults(test);
    iperf_set_test_role(test, 'c');
    iperf_set_test_server_hostname(test, host);
    iperf_set_test_server_port(test, port);
    iperf_set_test_duration(test, duration);
    iperf_set_test_reporter_interval(test, 1);
    iperf_set_test_stats_interval(test, 1);
    iperf_set_test_omit(test, 0);        // 不忽略开始的几秒
    iperf_set_verbose(test, 0);          // 禁用详细输出
    iperf_set_test_json_output(test, 1); // 启用 JSON 输出
    iperf_set_test_json_stream(test, 1);
    // iperf_set_test_logfile(test, "./iperf3.log");
    // 支持获取输出 JSON 字符串的回调函数，而不是将它们写入输出文件。 可使用 iperf_set_test_json_callback() 设置回调函数。
    iperf_set_test_json_callback(test, process_json);
    // 运行测试
    if (iperf_run_client(test) < 0)
    {
        // printf("Error running the test\n");
        // result.retcode = IPERF_ERROR_RUN_TEST;
        // snprintf(result.error_msg, sizeof(result.error_msg),
        //          "Error running test: %s", iperf_strerror(i_errno));
        iperf_free_test(test);
        return result;
    }

    iperf_free_test(test);
    result.bandwidth_upload = total_sent_bytes / total_time;
    result.bandwidth_download = total_received_bytes / total_time;
    return result;
}
